package br.com.future.dao;

import java.sql.Statement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import br.com.future.dao.interfaces.ProcessoDAOI;
import br.com.future.jdbc.ConnectionFactory;
import br.com.future.model.Advogado;
import br.com.future.model.AdvogadoProcesso;
import br.com.future.model.BloqueioDesbloqueio;
import br.com.future.model.Cliente;
import br.com.future.model.Forum;
import br.com.future.model.Processo;
import br.com.future.model.TipoCausa;
import br.com.future.model.TipoCobranca;

public class ProcessoDAO implements ProcessoDAOI {
	
	private Connection conn = null;
	private boolean flag = true;
	private Long numeroProcesso;

	public ProcessoDAO(Connection conn){
		this.conn  = conn;
	}
	
	public ProcessoDAO(){
		
	}

	@Override
	public Processo consultar(Long nProcesso) {
		
		verificarInstanciaDeConnection();
		
		
		String sql = "SELECT NR_PROCESSO, CD_PESSOA_FORUM, CD_PESSOA_CLIENTE, CD_CAUSA, CD_COBRANCA, DS_PROCESSO, DT_ABERTURA, DT_FECHAMENTO, DD_DIA_VENCIMENTO, CD_RESULTADO, DS_OBSERVACAO FROM AM_PROCESSO WHERE NR_PROCESSO = ?";

		PreparedStatement ps = null;

		ResultSet rs = null;
		Processo proces = null;
		
		try {

			ps = conn.prepareStatement(sql);
			ps.setLong(1, nProcesso);
			rs = ps.executeQuery();

			if (rs.next()) {
				
					Calendar dataFechamento = Calendar.getInstance();
					Calendar dataAbertura= Calendar.getInstance();
				
				    proces = new Processo();
					proces.setNumeroProcesso(rs.getLong("NR_PROCESSO"));
					proces.setDiaVencimento(rs.getInt("DD_DIA_VENCIMENTO"));
					proces.setDescricaoObservacao(rs.getString("DS_OBSERVACAO"));
					proces.setDescricaoProcesso(rs.getString("DS_PROCESSO"));
					//SETANDO A DATA DE ABERTURA
					dataAbertura.setTime(rs.getDate("DT_ABERTURA"));
					proces.setDataAbertura(dataAbertura);
					
					//UM PROCESSO TEM UM TIPO DE CAUSA
					TipoCausa tipoCausa = new TipoCausaDAO(conn).consultar(rs.getInt("CD_CAUSA"));
					proces.setTipoCausa(tipoCausa);
					
					//UM PROCESSO TEM UM TIPO DE PAGAMENTO
					TipoCobranca tipoCobranca = new TipoCobrancaDAO(conn).consultarPorId(rs.getInt("CD_COBRANCA"));
					proces.setTipoCobranca(tipoCobranca);
					
					//UM PROCESSO TEM UM FORUM
					Forum forum = new ForumDAO(conn).consultar(rs.getInt("CD_PESSOA_FORUM"));
					proces.setForum(forum);
					
					//UM PROCESSO TEM UM CLIENTE
					Cliente cliente = new ClienteDAO(conn).consultar(rs.getInt("CD_PESSOA_CLIENTE"));
					proces.setCliente(cliente);
					
					if(rs.getDate("DT_FECHAMENTO") != null){
						dataFechamento.setTime(rs.getDate("DT_FECHAMENTO"));
						proces.setDataFechamento(dataFechamento);
					}
					proces.setResultadoProcesso(rs.getInt("CD_RESULTADO"));
					
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			fecharConexao(ps, rs);
		}

		return proces;
	}
	
	public List<Processo> consultarHitoricoProcessos(){
		
		verificarInstanciaDeConnection();
		
		String sql ="SELECT HIST.NR_PROCESSO, HIST.DT_BLOQUEIO_DESBLOQ, COBRANCA.CD_COBRANCA, " +
					"       COBRANCA.DS_COBRANCA, BLOQ.CD_BLOQUEIO_DESBLOQ, BLOQ.DS_BLOQUEIO_DESBLOQ, " +
					"		CLIENTE.CD_PESSOA_CLIENTE, PESSOA.NM_PESSOA " +
					" FROM AM_HIST_PROC_BLOQ_DESBLOQ HIST " +
					" INNER JOIN AM_PROCESSO PROCESSO ON " +
					" 	  PROCESSO.NR_PROCESSO = HIST.NR_PROCESSO " +
					" INNER JOIN AM_TIPO_COBRANCA COBRANCA ON " +
					" 	  COBRANCA.CD_COBRANCA = PROCESSO.CD_COBRANCA " +
					" INNER JOIN AM_BLOQUEIO_DESBLOQ BLOQ ON " +
					" 	  BLOQ.CD_BLOQUEIO_DESBLOQ = HIST.CD_BLOQUEIO_DESBLOQ " +
					" INNER JOIN AM_CLIENTE CLIENTE ON " +
					" 	  CLIENTE.CD_PESSOA_CLIENTE = PROCESSO.CD_PESSOA_CLIENTE " +
					" INNER JOIN AM_PESSOA PESSOA ON " +
					" 	  PESSOA.CD_PESSOA = CLIENTE.CD_PESSOA_CLIENTE " +
					" ORDER BY HIST.DT_BLOQUEIO_DESBLOQ DESC";

		Statement stmt = null;
		ResultSet rs = null;
		List<Processo> processos = new ArrayList<Processo>();
		
		try{
			stmt = conn.createStatement();
			rs = stmt.executeQuery(sql);
			while(rs.next()){
				Calendar dtBloqDesblq = Calendar.getInstance();
				Processo processo = new Processo();
				Cliente cliente = new Cliente();
				BloqueioDesbloqueio bloqdesbloq = new BloqueioDesbloqueio();
				TipoCobranca cobranca = new TipoCobranca();
				processo.setNumeroProcesso(rs.getLong("NR_PROCESSO"));
				cliente.setCodigoPessoa(rs.getInt("CD_PESSOA_CLIENTE"));
				cliente.setNomePessoa(rs.getString("NM_PESSOA"));
				processo.setCliente(cliente);
				cobranca.setCodigoCobranca(rs.getInt("CD_COBRANCA"));
				cobranca.setDescricaoCobranca(rs.getString("DS_COBRANCA"));
				processo.setTipoCobranca(cobranca);
				bloqdesbloq.setCodigoBloqueioDesbloqueio(rs.getInt("CD_BLOQUEIO_DESBLOQ"));
				bloqdesbloq.setDescricaoBloqueioDesbloqueio(rs.getString("DS_BLOQUEIO_DESBLOQ"));
				
				dtBloqDesblq.setTime(rs.getDate("DT_BLOQUEIO_DESBLOQ"));
				bloqdesbloq.setDataBloqueioDesbloqueio(dtBloqDesblq);
				
				processo.setBloqdesbloq(bloqdesbloq);
				processos.add(processo);
				
			}
			
		}catch (SQLException e) {
			e.printStackTrace();
		}finally{
			if(flag){
				ConnectionFactory.closeConnectionOracle(conn, rs, stmt);
			}
		}
		
		return processos;
	}
	
	@Override
	public List<Processo> consultarTodos() {
		
		verificarInstanciaDeConnection();
		
		// INSTANCIAS DA DE CALENDAR
		
		
		String sql = "SELECT NR_PROCESSO, DS_OBSERVACAO, DS_PROCESSO, DT_ABERTURA, DT_FECHAMENTO, CD_RESULTADO, CD_CAUSA FROM AM_PROCESSO";

		PreparedStatement ps = null;

		ResultSet rs = null;

		List<Processo> processos = new ArrayList<Processo>();

		try {

			ps = conn.prepareStatement(sql);
			rs = ps.executeQuery();

			while (rs.next()) {
				Processo proces = new Processo();
				proces.setNumeroProcesso(rs.getLong("NR_PROCESSO"));
				proces.setDescricaoObservacao(rs.getString("DS_OBSERVACAO"));
				proces.setDescricaoProcesso(rs.getString("DS_PROCESSO"));
				
				//TRATANDO O CALENDAR
				
				Calendar dataFechamento = Calendar.getInstance();
				Calendar dataAbertura= Calendar.getInstance();
				
				//UM PROCESSO TEM UM TIPO DE CAUSA
				TipoCausa tipoCausa = new TipoCausaDAO(conn).consultar(rs.getInt("CD_CAUSA"));
				proces.setTipoCausa(tipoCausa);
				
				if(rs.getDate("DT_ABERTURA") != null){
					dataAbertura.setTime(rs.getDate("DT_ABERTURA"));
					proces.setDataAbertura(dataAbertura);
				}
				
				if(rs.getDate("DT_FECHAMENTO") != null){
					dataFechamento.setTime(rs.getDate("DT_FECHAMENTO"));
					proces.setDataFechamento(dataFechamento);
				}
				
				proces.setResultadoProcesso(rs.getInt("CD_RESULTADO"));
				processos.add(proces);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			fecharConexao(ps, rs);
		}

		return processos;
	}
	
	@Override
	public List<AdvogadoProcesso> consultarAdvogadosPorProcesso(Long nrProcesso){
		
		verificarInstanciaDeConnection();

		List<AdvogadoProcesso> advogadosProcesso = new ArrayList<AdvogadoProcesso>();
		PreparedStatement ps = null;
		ResultSet rs = null;
		
		String sql = "SELECT PESSOA.NM_PESSOA, PESSOA.CD_PESSOA, ADVOGADO.NR_OAB, ADV_PROC.DT_INICIO_PARTICIPACAO FROM "
						+" AM_ADVOGADO_PROCESSO ADV_PROC"
						+" INNER JOIN AM_ADVOGADO ADVOGADO ON "
						+" ADVOGADO.CD_PESSOA_ADV = ADV_PROC.CD_PESSOA_ADV"
						+" INNER JOIN AM_PESSOA PESSOA ON"
						+" ADVOGADO.CD_PESSOA_ADV = PESSOA.CD_PESSOA" 
						+" WHERE NR_PROCESSO = ?";
		try {

			ps = conn.prepareStatement(sql);
			ps.setLong(1, nrProcesso);
			rs = ps.executeQuery();

			while (rs.next()) {
				AdvogadoProcesso advProc = new AdvogadoProcesso();
				
				//SETANDO A DATA DE ABERTURA
				Calendar dataInicioParticipacao = Calendar.getInstance();
				dataInicioParticipacao.setTime(rs.getDate("DT_INICIO_PARTICIPACAO"));
				
				advProc.setDataInicioParticipacao(dataInicioParticipacao);
				
				Advogado advogado = new Advogado();
				advogado.setNomePessoa(rs.getString("NM_PESSOA"));
				advogado.setNumOAB(rs.getLong("NR_OAB"));
				advogado.setCodigoPessoa(rs.getInt("CD_PESSOA"));
				advProc.setAdvogado(advogado);

				advogadosProcesso.add(advProc);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			fecharConexao(ps, rs);
		}
		
		return advogadosProcesso;
	}
	
	@Override
	public void inserirProcesso(Processo processo, List<AdvogadoProcesso> advogadosProcesso) {
		verificarInstanciaDeConnection();
		
		String sql = "INSERT INTO AM_PROCESSO (CD_COBRANCA,CD_PESSOA_CLIENTE,CD_PESSOA_FORUM,DS_PROCESSO,DT_ABERTURA,DD_DIA_VENCIMENTO,CD_CAUSA, DS_OBSERVACAO) VALUES (?,?,?,?,?,?,?,?)";
		PreparedStatement ps = null;
		
		Calendar dataAbertura= Calendar.getInstance();
		
		try {
			ps = conn.prepareStatement(sql);
			ps.setInt(1, processo.getTipoCobranca().getCodigoCobranca());
			ps.setInt(2, processo.getCliente().getCodigoPessoa());
			ps.setInt(3, processo.getForum().getCodigoPessoa());
			ps.setString(4, processo.getDescricaoProcesso().toUpperCase());
			
			//dataAbertura.setTime(processo.getDataAbertura().getTime());
			ps.setDate(5, new java.sql.Date(dataAbertura.getTimeInMillis()));
			ps.setInt(6, processo.getDiaVencimento());
			ps.setInt(7, processo.getTipoCausa().getCodigo());
			ps.setString(8, processo.getDescricaoObservacao().toUpperCase());
			
			ps.executeUpdate();
			
			this.numeroProcesso = pegaSequenciaProcesso() - 1;
			
			for (AdvogadoProcesso advProc : advogadosProcesso) {
				inserirAdvNoProcesso(advProc);
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			if(flag){
				ConnectionFactory.closeConnectionOracle(conn, ps);
			}
		}
	}
	
	@Override
	public void inserirAdvNoProcesso(AdvogadoProcesso advogadoProcesso){
		verificarInstanciaDeConnection();
		
		String sql = "INSERT INTO AM_ADVOGADO_PROCESSO (NR_PROCESSO, CD_PESSOA_ADV, DT_INICIO_PARTICIPACAO) VALUES (?,?,?)";
		PreparedStatement ps = null;
		try {
			ps = conn.prepareStatement(sql);
			ps.setLong(1, numeroProcesso);
			ps.setInt(2, advogadoProcesso.getAdvogado().getCodigoPessoa());			
			ps.setDate(3, new java.sql.Date(advogadoProcesso.getDataInicioParticipacao().getTimeInMillis()));
			
			ps.executeUpdate();
			
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			if(flag){
				ConnectionFactory.closeConnectionOracle(conn, ps);
			}
		}
	}
	
	@Override
	public Long pegaSequenciaProcesso(){

		verificarInstanciaDeConnection();
		PreparedStatement ps = null;
		ResultSet rs = null;
		String sql = "SELECT AM_SQPROCESSO.NEXTVAL FROM DUAL";
		Long ultimaSequencia = 0L;
		try{
			ps = conn.prepareStatement(sql);
			rs = ps.executeQuery();
			
			if(rs.next()){
				ultimaSequencia = rs.getLong("NEXTVAL");
			}
		}catch(SQLException e){
			e.printStackTrace();
		}finally{
			fecharConexao(ps, rs);
		}
		return ultimaSequencia;
	}
	
	public boolean verificarProcessoLiberado(Long nrProcesso){
		verificarInstanciaDeConnection();
		
		PreparedStatement ps = null;
		ResultSet rs = null;
		String sql = "SELECT HIST.CD_BLOQUEIO_DESBLOQ, PROCESSO.DT_FECHAMENTO " +
					 " FROM AM_PROCESSO PROCESSO " +
					 " LEFT JOIN AM_HIST_PROC_BLOQ_DESBLOQ HIST ON " +
					 " PROCESSO.NR_PROCESSO = HIST.NR_PROCESSO " +
					 " WHERE PROCESSO.NR_PROCESSO = ? AND ROWNUM = 1 " +
					 " ORDER BY HIST.DT_BLOQUEIO_DESBLOQ DESC ";
		
		try{
			ps = conn.prepareStatement(sql);
			ps.setLong(1, nrProcesso);
			
			rs = ps.executeQuery();
			if(rs.next()){
				if(rs.getInt("CD_BLOQUEIO_DESBLOQ") == 1){
					fecharConexao(ps, rs);
					return false;
				}if(rs.getDate("DT_FECHAMENTO") != null){
					fecharConexao(ps, rs);
					return false;
				}else{
					return true;
				}
			}else{
				fecharConexao(ps, rs);
				return false;
			}
		}catch(SQLException e){
			e.printStackTrace();
			fecharConexao(ps, rs);
			return false;
		}finally{
			fecharConexao(ps, rs);
		}
	}

	private void fecharConexao(PreparedStatement ps, ResultSet rs) {
		if(flag){
			ConnectionFactory.closeConnectionOracle(conn, rs, ps);
		}
	}

	private void verificarInstanciaDeConnection() {
		flag = true;
		
		if(conn == null){
			conn = ConnectionFactory.getConnection();
		}else{
			flag = false;
		}
	}
	
	@Override
	public void alterarProcesso(Processo processo, List<AdvogadoProcesso> advogadosProcesso) {
		verificarInstanciaDeConnection();
		
		String sql = "UPDATE AM_PROCESSO SET CD_COBRANCA = ?,DD_DIA_VENCIMENTO = ?, DS_PROCESSO = ?, DS_OBSERVACAO = ? WHERE NR_PROCESSO = ?";
		PreparedStatement ps = null;
		
		System.out.println("tam: "+advogadosProcesso.size());
		
		try {
			ps = conn.prepareStatement(sql);
			ps.setInt(1,processo.getTipoCobranca().getCodigoCobranca());
			ps.setInt(2, processo.getDiaVencimento());
			ps.setString(3, processo.getDescricaoProcesso().toUpperCase());
			ps.setString(4, processo.getDescricaoObservacao().toUpperCase());
			ps.setLong(5, processo.getNumeroProcesso());
			ps.executeUpdate();
			
			this.numeroProcesso = processo.getNumeroProcesso();
			
			for (AdvogadoProcesso advProc : advogadosProcesso) {
				System.out.println(advProc.getAdvogado().getCodigoPessoa());
			}
			
			for (AdvogadoProcesso advProc : advogadosProcesso) {
				inserirAdvNoProcesso(advProc);
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			if(flag){
				ConnectionFactory.closeConnectionOracle(conn, ps);
			}
		}
	}
	
	@Override
	public void finalizarProcesso(Processo processo) {
		verificarInstanciaDeConnection();
		
		String sql = "UPDATE AM_PROCESSO SET CD_RESULTADO = ?, DT_FECHAMENTO = ? WHERE NR_PROCESSO = ?";
		PreparedStatement ps = null;
		
		try {
			ps = conn.prepareStatement(sql);
			ps.setInt(1,processo.getResultadoProcesso());
			
			Calendar dataFechamento = Calendar.getInstance();
			//dataFechamento.setTime(processo.getDataFechamento().getTime());
			ps.setDate(2, new java.sql.Date(dataFechamento.getTimeInMillis()));

			ps.setLong(3, processo.getNumeroProcesso());
			ps.executeUpdate();
			System.out.println("Finalizou o processo!");
			
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			if(flag){
				ConnectionFactory.closeConnectionOracle(conn, ps);
			}
		}
	}

	@Override
	public void removerAdvogadoDoProcesso(int codigoAdv, Long numProc) {
		
		verificarInstanciaDeConnection();
		
		String sql = "DELETE FROM AM_ADVOGADO_PROCESSO WHERE CD_PESSOA_ADV = ? AND NR_PROCESSO = ?";
		PreparedStatement ps = null;
		
		try {
			ps = conn.prepareStatement(sql);
			ps.setInt(1, codigoAdv);
			ps.setLong(2, numProc);
			ps.executeUpdate();
					
		}catch (SQLException e) {
			e.printStackTrace();
		}finally{
			if(flag){
				ConnectionFactory.closeConnectionOracle(conn, ps);
			}
		}
  }
}